/*
 * @Author: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Date: 2025-09-03 15:14:04
 * @LastEditTime: 2025-09-03 18:24:49
 * @LastEditors: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Description: 
 * @FilePath: \lc_-esp32_-s3\components\bsp\sdio\sd_card.c
 * 立创实战派ESP32-S3开发板
 * Copyright (c) 2025 by 4D Bios, All Rights Reserved. 
 */

#include "sd_card.h"

static const char *TAG = "sd_card";

sdmmc_card_t *card;                                                 /* SD / MMC卡结构 */
const char mount_point[] = MOUNT_POINT;                             /* 挂载点/根目录 */

/**
 * @description: SD卡初始化
 * @return {*}
 */
esp_err_t sd_init(void)
{
    esp_err_t ret;

    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = false,   // 如果挂载不成功是否需要格式化SD卡
        .max_files = 5, // 允许打开的最大文件数
        .allocation_unit_size = 16 * 1024  // 分配单元大小
    };
    
    const char mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");
    ESP_LOGI(TAG, "Using SDMMC peripheral");

    sdmmc_host_t host = SDMMC_HOST_DEFAULT(); // SDMMC主机接口配置
    sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); // SDMMC插槽配置
    slot_config.width = 1;  // 设置为1线SD模式
    slot_config.clk = BSP_SD_CLK; 
    slot_config.cmd = BSP_SD_CMD;
    slot_config.d0 = BSP_SD_D0;
    slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; // 打开内部上拉电阻

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card); // 挂载SD卡

    if (ret != ESP_OK) {  // 如果没有挂载成功
        if (ret == ESP_FAIL) { // 如果挂载失败
            ESP_LOGE(TAG, "Failed to mount filesystem. ");
        } else { // 如果是其它错误 打印错误名称
            ESP_LOGE(TAG, "Failed to initialize the card (%s). ", esp_err_to_name(ret));
        }
        return ret;
    }
    
    ESP_LOGI(TAG, "Filesystem mounted"); // 提示挂载成功
    sdmmc_card_print_info(stdout, card); // 终端打印SD卡的一些信息
    
    return ret;
}

/**
 * @brief       获取SD卡相关信息
 * @param       out_total_bytes：总大小
 * @param       out_free_bytes：剩余大小
 * @retval      无
 */
void sd_get_fatfs_usage(size_t *out_total_bytes, size_t *out_free_bytes)
{
    FATFS *fs;
    size_t free_clusters;
    int res = f_getfree("1:", (size_t *)&free_clusters, &fs);   //如果不初始化console中的storage，这里的值为"0:","1:"代表第二个FAT系统磁盘
    assert(res == FR_OK);
    size_t total_sectors = (fs->n_fatent - 2) * fs->csize;
    size_t free_sectors = free_clusters * fs->csize;

    size_t sd_total = total_sectors / 1024;
    size_t sd_total_KB = sd_total * fs->ssize;
    size_t sd_free = free_sectors / 1024;
    size_t sd_free_KB = sd_free*fs->ssize;

    /* 假设总大小小于4GiB，对于SPI Flash应该为true */
    if (out_total_bytes != NULL)
    {
        *out_total_bytes = sd_total_KB;
    }
    
    if (out_free_bytes != NULL)
    {
        *out_free_bytes = sd_free_KB;
    }
}

/**
 * @description: 卸载SD卡
 * @return {*}
 */
esp_err_t sd_unmount(void)
{
    esp_err_t ret;
    ret = esp_vfs_fat_sdcard_unmount(mount_point, card);

    if (ret != ESP_OK) {  // 如果没有卸载成功
        if (ret == ESP_FAIL) { // 如果卸载失败
            ESP_LOGE(TAG, "Failed to unmount filesystem. ");
        } else { // 如果是其它错误 打印错误名称
            ESP_LOGE(TAG, "Failed to unmount the card (%s). ", esp_err_to_name(ret));
        }
        return ret;
    }
    
    ESP_LOGI(TAG, "Card unmounted");

    return ret;
}